Skip to content

Conversation

@ArnabChatterjee20k
Copy link
Contributor

@ArnabChatterjee20k ArnabChatterjee20k commented Jan 14, 2026

Summary by CodeRabbit

  • New Features

    • Indexing and querying nested object attributes via dot‑notation (e.g., profile.user.email), including key/unique indexes and common comparison operators; improved JSON/object query reliability across adapters.
  • Bug Fixes / Validation

    • Stricter validation and clearer errors for nested-object index rules and attribute types; dotted-path queries are validated appropriately.
  • Tests

    • Extensive new end-to-end and unit tests covering nested-path indexes, queries, schemaless scenarios, and edge cases.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 14, 2026

📝 Walkthrough

Walkthrough

Adds dot‑notation (nested object path) support across Database, Mongo and Postgres adapters, and validators: index creation, query conversion, filter building, and validation updated to treat dotted object attributes appropriately; extensive unit and e2e tests added for nested‑path indexing and queries.

Changes

Cohort / File(s) Summary
Adapters: Mongo & Postgres
src/Database/Adapter/Mongo.php, src/Database/Adapter/Postgres.php
Mongo: split dotted index attributes, adjust buildFilter/handleObjectFilters to treat dotted paths and construct flattened keys from query attr. Postgres: added buildJsonbPath(string $path, bool $asText=false) and use it when indexing/querying nested JSONB paths.
Core Database logic
src/Database/Database.php
Resolve base attribute for dotted paths in createIndex/convertQuery, propagate adapter.getSupportForObject() into IndexValidator calls, and mark nested query attributes as object‑typed for downstream handling.
Validators: Index & Query Filter
src/Database/Validator/Index.php, src/Database/Validator/Query/Filter.php
Index validator gains supportForObjects flag, dotted‑attribute helpers and rules (require base to be OBJECT; disallow INDEX_OBJECT on dotted paths). Query filter treats dotted object‑path queries as text validators (skip object containment checks).
Tests: E2E & Unit
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php, tests/e2e/Adapter/Scopes/SchemalessTests.php, tests/unit/Validator/IndexTest.php
Adds comprehensive e2e tests for nested‑path index creation, uniqueness and queries (including schemaless Mongo dot‑notation test) and unit tests for nested index validation (some duplicated test blocks present).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Database
    participant Validator
    participant Adapter
    participant Engine

    Client->>Database: createIndex("profile.user.email", type)
    Database->>Validator: checkValidIndex("profile.user.email", supportForObjects)
    Validator->>Validator: extract base "profile" and verify type == OBJECT
    Validator-->>Database: valid / invalid
    Database->>Adapter: createIndex(processed expression)
    Adapter->>Adapter: build expression (Mongo dot-path / Postgres JSONB via buildJsonbPath)
    Adapter->>Engine: CREATE INDEX on expression
    Engine-->>Adapter: result
    Adapter-->>Database: success
    Database-->>Client: index created
Loading
sequenceDiagram
    participant Client
    participant Database
    participant QueryConverter
    participant Validator
    participant Adapter
    participant Engine

    Client->>Database: query(profile.user.email = "[email protected]")
    Database->>QueryConverter: detect dotted attribute
    QueryConverter->>QueryConverter: derive base "profile", mark as OBJECT
    QueryConverter-->>Database: set attribute type = OBJECT (dotted)
    Database->>Validator: validate filter as TEXT for dotted object path
    Validator-->>Database: valid
    Database->>Adapter: build filter (JSONB/text or Mongo dot access)
    Adapter->>Engine: execute query with nested path expression
    Engine-->>Adapter: results
    Adapter-->>Database: documents
    Database-->>Client: filtered results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • abnegate

Poem

🐇
I hop through dots and stitch a trail,
profile.user.email — a tiny tale.
Indexes hum where nesting grew,
Queries find the path made true.
A rabbit cheered: "Works through and through!"

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Object attribute query and index' directly reflects the main changes: adding support for querying and indexing nested object attributes through dot notation across multiple adapters and validators.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nested-object-index

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ArnabChatterjee20k
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Database/Validator/Query/Filter.php (1)

86-189: Bug: dotted-object path values skip validation due to continue 2.

When $isDottedOnObject is true you create a Text validator but continue 2; bypasses the actual $validator->isValid($value) check. This can let non-strings through and blow up later in adapters (e.g., string ops for LIKE/regex).

Proposed fix
@@
                 case Database::VAR_OBJECT:
                     // For dotted attributes on objects, validate as string (path queries)
                     if ($isDottedOnObject) {
                         $validator = new Text(0, 0);
-                        continue 2;
+                        break;
                     }
 
-                    // object containment queries on the base object attribute
-                    elseif (\in_array($method, [Query::TYPE_EQUAL, Query::TYPE_NOT_EQUAL, Query::TYPE_CONTAINS, Query::TYPE_NOT_CONTAINS], true)
+                    // object containment queries on the base object attribute
+                    if (\in_array($method, [Query::TYPE_EQUAL, Query::TYPE_NOT_EQUAL, Query::TYPE_CONTAINS, Query::TYPE_NOT_CONTAINS], true)
                         && !$this->isValidObjectQueryValues($value)) {
                         $this->message = 'Invalid object query structure for attribute "' . $attribute . '"';
                         return false;
                     }
 
                     continue 2;
🤖 Fix all issues with AI agents
In `@src/Database/Validator/Index.php`:
- Around line 768-776: Both helper methods lack return type declarations causing
PHPStan failures; add explicit return types: change isDottedAttribute(string
$attribute) to return bool and change getBaseAttributeFromDottedAttribute(string
$attribute) to return string (i.e., add ": bool" and ": string" to the
respective method signatures), keeping the current logic intact.
- Around line 169-180: The current loop in Index.php incorrectly iterates over
all index attributes and enforces object-type on non-dotted attributes; change
the loop to iterate only over $dottedAttributes (the result of array_filter) so
the object-type check runs only for dotted attributes, derive $baseAttribute via
getBaseAttributeFromDottedAttribute($attribute) as already intended, and keep
the existing error message/return false when the base attribute exists but is
not Database::VAR_OBJECT.

In `@tests/e2e/Adapter/Scopes/ObjectAttributeTests.php`:
- Around line 1180-1190: Remove the redundant if-check around the object-index
test: the outer test already skipped when getSupportForObjectIndexes() is false,
so delete the conditional "if
($database->getAdapter()->getSupportForObjectIndexes()) {" and its matching
closing brace, leaving the try/catch that creates the index
'idx_profile_nested_object' with Database::INDEX_OBJECT and the subsequent
assertions intact; make sure the block still catches Exception $e and asserts
InstanceOf IndexException and that $exceptionThrown is asserted true.
🧹 Nitpick comments (4)
src/Database/Adapter/Postgres.php (1)

1751-1772: Good nested-path handling; consider aliasing SEARCH/NOT_SEARCH for consistency.

filterObjectPath() + skipping handleObjectQueries() for nested paths makes sense. One gotcha: TYPE_SEARCH/TYPE_NOT_SEARCH uses regexp_replace({$attribute}, ...) without the table alias, which can become ambiguous in joined queries; using {$alias}.{$attribute} would be safer for both simple and nested paths.

Proposed tweak
@@
             case Query::TYPE_SEARCH:
                 $binds[":{$placeholder}_0"] = $this->getFulltextValue($query->getValue());
-                return "to_tsvector(regexp_replace({$attribute}, '[^\w]+',' ','g')) @@ websearch_to_tsquery(:{$placeholder}_0)";
+                return "to_tsvector(regexp_replace({$alias}.{$attribute}, '[^\w]+',' ','g')) @@ websearch_to_tsquery(:{$placeholder}_0)";
 
             case Query::TYPE_NOT_SEARCH:
                 $binds[":{$placeholder}_0"] = $this->getFulltextValue($query->getValue());
-                return "NOT (to_tsvector(regexp_replace({$attribute}, '[^\w]+',' ','g')) @@ websearch_to_tsquery(:{$placeholder}_0))";
+                return "NOT (to_tsvector(regexp_replace({$alias}.{$attribute}, '[^\w]+',' ','g')) @@ websearch_to_tsquery(:{$placeholder}_0))";
tests/unit/Validator/IndexTest.php (1)

328-439: Test coverage is solid; small readability nits.

  • $validNestedObjectIndex is asserted false → rename to $invalidNestedObjectIndex.
  • Consider using named args for the new Index(...) constructor here (positional booleans are brittle).
Minimal rename
@@
-        $validNestedObjectIndex = new Document([
+        $invalidNestedObjectIndex = new Document([
             '$id' => ID::custom('idx_nested_object'),
             'type' => Database::INDEX_OBJECT,
             'attributes' => ['data.key.nestedKey'],
             'lengths' => [],
             'orders' => [],
         ]);
 
-        $this->assertFalse($validator->isValid($validNestedObjectIndex));
+        $this->assertFalse($validator->isValid($invalidNestedObjectIndex));
src/Database/Database.php (2)

8147-8162: Minor perf/clarity: compute the base attribute once for nested-object query inference.

Right now explode() happens inside the loop; you can compute $baseAttribute once and reuse $queryAttribute consistently.


3638-3715: Make base-attribute matching more robust for dot-path indexes (key fallback + case-insensitive compare).

validateAttribute() treats attribute IDs case-insensitively, but createIndex() matches $baseAttr against key with a case-sensitive comparison. That can leave $indexAttributesWithTypes incomplete (and skip length/array adjustments) if callers pass a different case, or if an attribute lacks key.

Proposed tweak (more defensive matching)
-            $baseAttr = $attr;
-            if (\str_contains($attr, '.')) {
-                $baseAttr = \explode('.', $attr, 2)[0] ?? $attr;
-            }
+            $baseAttr = \str_contains($attr, '.')
+                ? \explode('.', $attr, 2)[0]
+                : $attr;
+            $baseAttrLc = \strtolower($baseAttr);

             foreach ($collectionAttributes as $collectionAttribute) {
-                if ($collectionAttribute->getAttribute('key') === $baseAttr) {
+                $collectionAttrKey = (string)$collectionAttribute->getAttribute('key', $collectionAttribute->getId());
+                if (\strtolower($collectionAttrKey) === $baseAttrLc) {
                     $attributeType = $collectionAttribute->getAttribute('type');
                     $indexAttributesWithTypes[$attr] = $attributeType;
#!/bin/bash
set -euo pipefail

# Ensure Adapter::createIndex signature/arity matches this call (and all implementations are updated).
rg -nP '\bfunction\s+createIndex\s*\('
rg -nP '->createIndex\s*\('
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e491ed2 and 17c6359.

📒 Files selected for processing (8)
  • src/Database/Adapter/Mongo.php
  • src/Database/Adapter/Postgres.php
  • src/Database/Database.php
  • src/Database/Validator/Index.php
  • src/Database/Validator/Query/Filter.php
  • tests/e2e/Adapter/Scopes/ObjectAttributeTests.php
  • tests/e2e/Adapter/Scopes/SchemalessTests.php
  • tests/unit/Validator/IndexTest.php
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-10-03T02:04:17.803Z
Learnt from: abnegate
Repo: utopia-php/database PR: 721
File: tests/e2e/Adapter/Scopes/DocumentTests.php:6418-6439
Timestamp: 2025-10-03T02:04:17.803Z
Learning: In tests/e2e/Adapter/Scopes/DocumentTests::testSchemalessDocumentInvalidInteralAttributeValidation (PHP), when the adapter reports getSupportForAttributes() === false (schemaless), the test should not expect exceptions from createDocuments for “invalid” internal attributes; remove try/catch and ensure the test passes without exceptions, keeping at least one assertion.

Applied to files:

  • tests/unit/Validator/IndexTest.php
  • src/Database/Adapter/Mongo.php
  • tests/e2e/Adapter/Scopes/SchemalessTests.php
  • tests/e2e/Adapter/Scopes/ObjectAttributeTests.php
📚 Learning: 2025-10-29T12:27:57.071Z
Learnt from: ArnabChatterjee20k
Repo: utopia-php/database PR: 747
File: src/Database/Adapter/Mongo.php:1449-1453
Timestamp: 2025-10-29T12:27:57.071Z
Learning: In src/Database/Adapter/Mongo.php, when getSupportForAttributes() returns false (schemaless mode), the updateDocument method intentionally uses a raw document without $set operator for replacement-style updates, as confirmed by the repository maintainer ArnabChatterjee20k.

Applied to files:

  • src/Database/Adapter/Mongo.php
  • tests/e2e/Adapter/Scopes/SchemalessTests.php
📚 Learning: 2025-10-03T01:50:11.943Z
Learnt from: abnegate
Repo: utopia-php/database PR: 721
File: tests/e2e/Adapter/Scopes/AttributeTests.php:1329-1334
Timestamp: 2025-10-03T01:50:11.943Z
Learning: MongoDB has a 1024kb (1,048,576 bytes) limit for index entries. The MongoDB adapter's getMaxIndexLength() method should return this limit rather than 0.

Applied to files:

  • src/Database/Adapter/Mongo.php
📚 Learning: 2025-11-25T10:46:37.666Z
Learnt from: fogelito
Repo: utopia-php/database PR: 763
File: src/Database/Database.php:8671-8751
Timestamp: 2025-11-25T10:46:37.666Z
Learning: In Utopia\Database\Database::processRelationshipQueries, ensure the system select for '$id' is added only when the collection has relationship attributes (i.e., !empty($relationships)), and avoid capturing the unused '$idAdded' from Query::addSelect to satisfy static analysis.

Applied to files:

  • src/Database/Database.php
📚 Learning: 2025-10-20T05:29:29.487Z
Learnt from: abnegate
Repo: utopia-php/database PR: 731
File: src/Database/Database.php:6987-6988
Timestamp: 2025-10-20T05:29:29.487Z
Learning: In Utopia\Database\Database::convertRelationshipQueries, Many-to-Many filtering does not need the parent collection or a direct junction query: it calls find() on the related collection without skipping relationships, which populates relationship attributes (including the two-way key). Parent IDs are derived from that populated attribute. Therefore, calls should remain convertRelationshipQueries($relationships, $queries).

Applied to files:

  • src/Database/Database.php
📚 Learning: 2025-10-16T09:37:33.531Z
Learnt from: fogelito
Repo: utopia-php/database PR: 733
File: src/Database/Adapter/MariaDB.php:1801-1806
Timestamp: 2025-10-16T09:37:33.531Z
Learning: In the MariaDB adapter (src/Database/Adapter/MariaDB.php), only duplicate `_uid` violations should throw `DuplicateException`. All other unique constraint violations, including `PRIMARY` key collisions on the internal `_id` field, should throw `UniqueException`. This is the intended design to distinguish between user-facing document duplicates and internal/user-defined unique constraint violations.

Applied to files:

  • tests/e2e/Adapter/Scopes/ObjectAttributeTests.php
📚 Learning: 2025-07-01T11:31:37.438Z
Learnt from: ArnabChatterjee20k
Repo: utopia-php/database PR: 613
File: src/Database/Adapter/Postgres.php:1254-1319
Timestamp: 2025-07-01T11:31:37.438Z
Learning: In PostgreSQL adapter methods like getUpsertStatement, complexity for database-specific SQL generation is acceptable when the main business logic is properly separated in the parent SQL adapter class, following the adapter pattern where each database adapter handles its own SQL syntax requirements.

Applied to files:

  • src/Database/Adapter/Postgres.php
📚 Learning: 2025-07-30T19:17:53.630Z
Learnt from: ArnabChatterjee20k
Repo: utopia-php/database PR: 642
File: src/Database/Validator/PartialStructure.php:43-52
Timestamp: 2025-07-30T19:17:53.630Z
Learning: In PartialStructure validator, when filtering for required attributes validation using the $requiredAttributes parameter, $this->attributes should be used instead of the merged $attributes array because this validation is specifically for internal attributes like $createdAt and $updatedAt that are defined in the base Structure class, not collection-specific attributes.

Applied to files:

  • src/Database/Validator/Query/Filter.php
🧬 Code graph analysis (6)
src/Database/Validator/Index.php (1)
src/Database/Database.php (1)
  • Database (37-8812)
src/Database/Adapter/Mongo.php (2)
src/Database/Adapter.php (1)
  • filter (1255-1264)
src/Database/Adapter/SQL.php (1)
  • getInternalKeyForAttribute (2383-2395)
tests/e2e/Adapter/Scopes/SchemalessTests.php (1)
src/Database/Adapter/Mongo.php (3)
  • getSupportForAttributes (2792-2795)
  • createCollection (408-572)
  • createIndex (907-1034)
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (6)
src/Database/Database.php (2)
  • Database (37-8812)
  • getDatabase (914-917)
src/Database/Adapter.php (2)
  • getDatabase (162-165)
  • getSupportForObjectIndexes (1087-1087)
src/Database/Adapter/Postgres.php (1)
  • getSupportForObjectIndexes (2241-2244)
src/Database/Adapter/MySQL.php (1)
  • getSupportForObjectIndexes (256-259)
src/Database/Adapter/SQLite.php (1)
  • getSupportForObjectIndexes (1021-1024)
src/Database/Adapter/MariaDB.php (1)
  • getSupportForObjectIndexes (2148-2151)
src/Database/Adapter/Postgres.php (3)
src/Database/Adapter.php (2)
  • filter (1255-1264)
  • quote (469-469)
src/Database/Query.php (2)
  • isObjectAttribute (999-1002)
  • getAttribute (182-185)
src/Database/Document.php (1)
  • getAttribute (224-231)
src/Database/Validator/Query/Filter.php (2)
src/Database/Database.php (1)
  • Database (37-8812)
src/Database/Query.php (1)
  • Query (8-1237)
🪛 GitHub Actions: CodeQL
src/Database/Validator/Index.php

[error] 768-768: isDottedAttribute() has no return type specified. (PHPStan: missing return type)


[error] 773-773: getBaseAttributeFromDottedAttribute() has no return type specified. (PHPStan: missing return type)

tests/e2e/Adapter/Scopes/ObjectAttributeTests.php

[error] 1181-1181: If condition is always true. (PHPStan: always-true conditional)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Adapter Tests (MariaDB)
  • GitHub Check: Adapter Tests (SharedTables/SQLite)
  • GitHub Check: Adapter Tests (SharedTables/Postgres)
  • GitHub Check: Adapter Tests (SharedTables/MariaDB)
  • GitHub Check: Adapter Tests (Schemaless/MongoDB)
  • GitHub Check: Adapter Tests (Mirror)
  • GitHub Check: Adapter Tests (Pool)
  • GitHub Check: Adapter Tests (SharedTables/MongoDB)
  • GitHub Check: Adapter Tests (SharedTables/MySQL)
  • GitHub Check: Adapter Tests (MongoDB)
  • GitHub Check: Adapter Tests (MySQL)
  • GitHub Check: Adapter Tests (SQLite)
  • GitHub Check: Adapter Tests (Postgres)
🔇 Additional comments (7)
src/Database/Adapter/Postgres.php (1)

884-899: No action needed. The code correctly handles nested path indexing. The $indexAttributesWithTypes parameter passed from Database.php::createIndex() is keyed by the full dotted attribute path, so the isset($indexAttributeTypes[$attr]) check in Postgres.php works as intended.

src/Database/Validator/Index.php (3)

251-266: LGTM!

The validation logic correctly allows dotted attributes when object indexes are supported and the base attribute exists.


401-403: LGTM!

Correctly resolves dotted attributes to their base for index length validation.


749-755: LGTM!

Correctly enforces that INDEX_OBJECT can only be created on top-level object attributes, preventing invalid GIN indexes on nested paths.

tests/e2e/Adapter/Scopes/SchemalessTests.php (1)

1869-1958: LGTM!

Comprehensive test coverage for dot-notation indexing in schemaless adapters:

  • Correctly gates test for schemaless-only execution
  • Validates both KEY and UNIQUE index creation on nested paths
  • Verifies unique constraint enforcement with expected DuplicateException
  • Tests dot-notation query functionality
tests/e2e/Adapter/Scopes/ObjectAttributeTests.php (2)

8-8: LGTM!

Import correctly added for DuplicateException used in the new tests.


1205-1333: LGTM!

Excellent test coverage for querying nested object attributes:

  • Tests multiple query operators (equal, startsWith, endsWith, contains, notEndsWith)
  • Validates logical combinations (AND, OR)
  • Properly seeds test data with varied nested structures

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@ArnabChatterjee20k ArnabChatterjee20k changed the base branch from 3.x to main February 10, 2026 05:52
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/Database/Database.php`:
- Around line 2872-2895: The IndexValidator instantiation block is over-indented
under the surrounding if ($altering) scope causing a Pint PSR-12
statement_indentation failure; reformat the block so its indentation aligns with
the surrounding code style (match other method calls/constructors in the file),
ensuring the if ($this->validate) { ... } block and the new IndexValidator(...)
call use the correct 4-space indentation and argument alignment for PSR-12
(e.g., arguments indented one level inside the parentheses and the closing );
aligned with the opening line) so Pint passes; update the lines around the
IndexValidator, $this->validate check, and the surrounding if ($altering) scope
accordingly.

In `@tests/e2e/Adapter/Scopes/ObjectAttributeTests.php`:
- Around line 1545-1558: The local variable $updated returned from the call to
$database->updateDocument($collectionId, 'mixed1', new Document(...)) is unused
and flagged by PHPMD; either remove the assignment and call
$database->updateDocument(...) directly, or keep the assignment and make use of
$updated (for example assert its contents or check fields) so it is referenced;
locate the updateDocument call and the $updated variable in the test (variable
name $updated) and apply one of these two fixes to eliminate the unused variable
warning.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@tests/e2e/Adapter/Scopes/ObjectAttributeTests.php`:
- Around line 1180-1185: The test currently calls
$database->createIndex($collectionId, 'idx_profile_nested_object',
Database::INDEX_OBJECT, ['profile.user.email']) expecting an IndexException but
never fails if no exception is thrown; update the try block to assert failure
when createIndex succeeds by adding a $this->fail('Expected IndexException when
creating INDEX_OBJECT on nested path') immediately after the createIndex call
(or use the existing $exceptionThrown boolean pattern used elsewhere in this
test file) and keep the catch verifying the exception is an instance of
IndexException.

In `@tests/e2e/Adapter/Scopes/SchemalessTests.php`:
- Around line 3161-3164: The test currently only guards on
getSupportForAttributes(); add a guard for object support as well by checking
$database->getAdapter()->getSupportForObject() and returning early with
$this->expectNotToPerformAssertions() if it returns false so the test skips on
schemaless adapters without object support; mirror the check used in
testSchemalessObjectIndexes to ensure the object-attribute and nested object
index creation is only executed when both getSupportForAttributes() and
getSupportForObject() are true.
🧹 Nitpick comments (1)
tests/e2e/Adapter/Scopes/SchemalessTests.php (1)

3155-3155: Consider a more adapter-agnostic method name.

The method is named testSchemalessMongoDotNotationIndexes but lives in a generic SchemalessTests trait that could be used by any schemaless adapter. A name like testSchemalessNestedObjectPathIndexes or testSchemalessDotNotationIndexes would be more consistent with the rest of the trait.

Comment on lines +1180 to +1185
// 3) INDEX_OBJECT must NOT be allowed on nested paths
try {
$database->createIndex($collectionId, 'idx_profile_nested_object', Database::INDEX_OBJECT, ['profile.user.email']);
} catch (Exception $e) {
$this->assertInstanceOf(IndexException::class, $e);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing failure assertion — test silently passes if INDEX_OBJECT on nested path is allowed.

If createIndex does not throw, the test never fails. Add a $this->fail(...) after the call (or use the $exceptionThrown pattern used elsewhere in this file).

Proposed fix
         // 3) INDEX_OBJECT must NOT be allowed on nested paths
+        $exceptionThrown = false;
         try {
             $database->createIndex($collectionId, 'idx_profile_nested_object', Database::INDEX_OBJECT, ['profile.user.email']);
+            $this->fail('Expected Index exception for object index on nested path');
         } catch (Exception $e) {
+            $exceptionThrown = true;
             $this->assertInstanceOf(IndexException::class, $e);
         }
+        $this->assertTrue($exceptionThrown, 'Expected Index exception for object index on nested path');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// 3) INDEX_OBJECT must NOT be allowed on nested paths
try {
$database->createIndex($collectionId, 'idx_profile_nested_object', Database::INDEX_OBJECT, ['profile.user.email']);
} catch (Exception $e) {
$this->assertInstanceOf(IndexException::class, $e);
}
// 3) INDEX_OBJECT must NOT be allowed on nested paths
$exceptionThrown = false;
try {
$database->createIndex($collectionId, 'idx_profile_nested_object', Database::INDEX_OBJECT, ['profile.user.email']);
$this->fail('Expected Index exception for object index on nested path');
} catch (Exception $e) {
$exceptionThrown = true;
$this->assertInstanceOf(IndexException::class, $e);
}
$this->assertTrue($exceptionThrown, 'Expected Index exception for object index on nested path');
🤖 Prompt for AI Agents
In `@tests/e2e/Adapter/Scopes/ObjectAttributeTests.php` around lines 1180 - 1185,
The test currently calls $database->createIndex($collectionId,
'idx_profile_nested_object', Database::INDEX_OBJECT, ['profile.user.email'])
expecting an IndexException but never fails if no exception is thrown; update
the try block to assert failure when createIndex succeeds by adding a
$this->fail('Expected IndexException when creating INDEX_OBJECT on nested path')
immediately after the createIndex call (or use the existing $exceptionThrown
boolean pattern used elsewhere in this test file) and keep the catch verifying
the exception is an instance of IndexException.

Comment on lines +3161 to +3164
if ($database->getAdapter()->getSupportForAttributes()) {
$this->expectNotToPerformAssertions();
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing getSupportForObject() guard — test may fail on schemaless adapters without object support.

The existing testSchemalessObjectIndexes (Line 761) checks both getSupportForAttributes() and getSupportForObject() before running. This test creates an object attribute and indexes on nested object paths, so it should similarly guard against adapters that don't support objects.

Proposed fix
-        if ($database->getAdapter()->getSupportForAttributes()) {
+        if ($database->getAdapter()->getSupportForAttributes() || !$database->getAdapter()->getSupportForObject()) {
             $this->expectNotToPerformAssertions();
             return;
         }
🤖 Prompt for AI Agents
In `@tests/e2e/Adapter/Scopes/SchemalessTests.php` around lines 3161 - 3164, The
test currently only guards on getSupportForAttributes(); add a guard for object
support as well by checking $database->getAdapter()->getSupportForObject() and
returning early with $this->expectNotToPerformAssertions() if it returns false
so the test skips on schemaless adapters without object support; mirror the
check used in testSchemalessObjectIndexes to ensure the object-attribute and
nested object index creation is only executed when both
getSupportForAttributes() and getSupportForObject() are true.

@abnegate abnegate merged commit b18ff43 into main Feb 12, 2026
32 of 33 checks passed
@abnegate abnegate deleted the nested-object-index branch February 12, 2026 07:00
@coderabbitai coderabbitai bot mentioned this pull request Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants